package handlers

import (
	"fmt"
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/sirupsen/logrus"
	"github.com/yourusername/virt-manager-go/internal/models"
	"github.com/yourusername/virt-manager-go/internal/service"
	libvirtlib "libvirt.org/go/libvirt"
)

// StorageHandler handles storage pool and volume requests
type StorageHandler struct {
	connMgr *service.ConnectionManager
	log     *logrus.Logger
}

// NewStorageHandler creates a new storage handler
func NewStorageHandler(connMgr *service.ConnectionManager, log *logrus.Logger) *StorageHandler {
	return &StorageHandler{
		connMgr: connMgr,
		log:     log,
	}
}

// ListPools returns all storage pools
//
//	@Summary		List storage pools
//	@Description	Returns all storage pools for a specific connection
//	@Tags			storage
//	@Accept			json
//	@Produce		json
//	@Param			connection	query		string					false	"Connection ID"
//	@Success		200			{object}	map[string]interface{}	"{"pools": []models.StoragePoolSummary, "count": int}"
//	@Failure		500			{object}	map[string]interface{}	"Internal Server Error"
//	@Router			/storage/pools [get]
func (h *StorageHandler) ListPools(c *gin.Context) {
	conn, err := getConnectionFromRequest(c, h.connMgr)
	if err != nil {
		h.log.WithError(err).Error("Failed to get connection")
		c.JSON(http.StatusInternalServerError, gin.H{"error": "connection not available"})
		return
	}

	hvConn := conn.GetConnect()
	pools, err := hvConn.ListAllStoragePools(libvirtlib.CONNECT_LIST_STORAGE_POOLS_ACTIVE | libvirtlib.CONNECT_LIST_STORAGE_POOLS_INACTIVE)
	if err != nil {
		h.log.WithError(err).Error("Failed to list storage pools")
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	result := make([]models.StoragePoolSummary, 0, len(pools))
	for _, pool := range pools {
		name, _ := pool.GetName()
		uuid, _ := pool.GetUUIDString()
		active, _ := pool.IsActive()

		xmlDesc, _ := pool.GetXMLDesc(0)
		poolType := "unknown"
		if xmlDesc != "" {
			// Parse type from XML if needed
			poolType = "dir" // Default to dir
		}

		result = append(result, models.StoragePoolSummary{
			Name:   name,
			UUID:   uuid,
			Active: active,
			Type:   poolType,
		})

		if err := pool.Free(); err != nil {
			// 记录错误但继续执行
			h.log.WithError(err).Warn("Failed to free storage pool")
		}
	}

	c.JSON(http.StatusOK, gin.H{
		"pools": result,
		"count": len(result),
	})
}

// GetPool returns a specific storage pool
//
//	@Summary		Get storage pool details
//	@Description	Returns detailed information about a specific storage pool
//	@Tags			storage
//	@Accept			json
//	@Produce		json
//	@Param			connection	query		string	true	"Connection ID"
//	@Param			pool		query		string	true	"Storage pool name"
//	@Success		200			{object}	models.StoragePoolDetail
//	@Failure		404			{object}	map[string]interface{}	"Storage pool not found"
//	@Failure		500			{object}	map[string]interface{}	"Internal Server Error"
//	@Router			/storage/pool [get]
func (h *StorageHandler) GetPool(c *gin.Context) {
	name := c.Query("pool")
	if name == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "pool query parameter is required"})
		return
	}

	conn, err := getConnectionFromRequest(c, h.connMgr)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "connection not available"})
		return
	}

	hvConn := conn.GetConnect()

	pool, err := hvConn.LookupStoragePoolByName(name)
	if err != nil {
		h.log.WithError(err).WithField("name", name).Error("Storage pool not found")
		c.JSON(http.StatusNotFound, gin.H{"error": "storage pool not found"})
		return
	}
	defer func() {
		if err := pool.Free(); err != nil {
			// 记录错误但继续执行
			h.log.WithError(err).Warn("Failed to free storage pool")
		}
	}()

	uuid, _ := pool.GetUUIDString()
	active, _ := pool.IsActive()
	info, _ := pool.GetInfo()
	xmlDesc, _ := pool.GetXMLDesc(0)

	c.JSON(http.StatusOK, models.StoragePoolDetail{
		Name:       name,
		UUID:       uuid,
		Active:     active,
		Type:       "dir",
		Capacity:   info.Capacity,
		Allocation: info.Allocation,
		Available:  info.Available,
		XMLConfig:  xmlDesc,
	})
}

// CreatePool creates a new storage pool
//
//	@Summary		Create storage pool
//	@Description	Creates a new storage pool
//	@Tags			storage
//	@Accept			json
//	@Produce		json
//	@Param			connection	query		string					false	"Connection ID"
//	@Param			xml_config	body		string					true	"Storage pool XML configuration"
//	@Success		201			{object}	map[string]interface{}	"{"message": string}"
//	@Failure		400			{object}	map[string]interface{}	"Bad Request"
//	@Failure		500			{object}	map[string]interface{}	"Internal Server Error"
//	@Router			/storage/pools [post]
func (h *StorageHandler) CreatePool(c *gin.Context) {
	var req struct {
		XMLConfig string `json:"xml_config" binding:"required"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	conn, err := getConnectionFromRequest(c, h.connMgr)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "connection not available"})
		return
	}

	hvConn := conn.GetConnect()
	pool, err := hvConn.StoragePoolDefineXML(req.XMLConfig, 0)
	if err != nil {
		h.log.WithError(err).Error("Failed to create storage pool")
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	defer func() {
		if err := pool.Free(); err != nil {
			// 记录错误但继续执行
			h.log.WithError(err).Warn("Failed to free storage pool")
		}
	}()

	name, _ := pool.GetName()
	h.log.WithField("name", name).Info("Storage pool created successfully")
	c.JSON(http.StatusCreated, gin.H{"message": "storage pool created successfully"})
}

// DeletePool deletes a storage pool
//
//	@Summary		Delete storage pool
//	@Description	Deletes a storage pool
//	@Tags			storage
//	@Accept			json
//	@Produce		json
//	@Param			connection	query		string					true	"Connection ID"
//	@Param			pool		query		string					true	"Storage pool name"
//	@Success		200			{object}	map[string]interface{}	"{"message": string}"
//	@Failure		404			{object}	map[string]interface{}	"Storage pool not found"
//	@Failure		500			{object}	map[string]interface{}	"Internal Server Error"
//	@Router			/storage/pool [delete]
func (h *StorageHandler) DeletePool(c *gin.Context) {
	name := c.Query("pool")
	if name == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "pool query parameter is required"})
		return
	}

	conn, err := getConnectionFromRequest(c, h.connMgr)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "connection not available"})
		return
	}

	hvConn := conn.GetConnect()

	pool, err := hvConn.LookupStoragePoolByName(name)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "storage pool not found"})
		return
	}
	defer func() {
		if err := pool.Free(); err != nil {
			// 记录错误但继续执行
			h.log.WithError(err).Warn("Failed to free storage pool")
		}
	}()

	if err := pool.Undefine(); err != nil {
		h.log.WithError(err).Error("Failed to delete storage pool")
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	h.log.WithField("name", name).Info("Storage pool deleted successfully")
	c.JSON(http.StatusOK, gin.H{"message": "storage pool deleted successfully"})
}

// StartPool starts a storage pool
//
//	@Summary		Start storage pool
//	@Description	Starts a storage pool
//	@Tags			storage
//	@Accept			json
//	@Produce		json
//	@Param			connection	query		string					true	"Connection ID"
//	@Param			pool		query		string					true	"Storage pool name"
//	@Success		200			{object}	map[string]interface{}	"{"message": string}"
//	@Failure		404			{object}	map[string]interface{}	"Storage pool not found"
//	@Failure		500			{object}	map[string]interface{}	"Internal Server Error"
//	@Router			/storage/pool/start [post]
func (h *StorageHandler) StartPool(c *gin.Context) {
	name := c.Query("pool")
	if name == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "pool query parameter is required"})
		return
	}

	conn, err := getConnectionFromRequest(c, h.connMgr)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "connection not available"})
		return
	}

	hvConn := conn.GetConnect()

	pool, err := hvConn.LookupStoragePoolByName(name)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "storage pool not found"})
		return
	}
	defer func() {
		if err := pool.Free(); err != nil {
			// 记录错误但继续执行
			h.log.WithError(err).Warn("Failed to free storage pool")
		}
	}()

	if err := pool.Create(0); err != nil {
		h.log.WithError(err).Error("Failed to start storage pool")
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	h.log.WithField("name", name).Info("Storage pool started successfully")
	c.JSON(http.StatusOK, gin.H{"message": "storage pool started successfully"})
}

// StopPool stops a storage pool
//
//	@Summary		Stop storage pool
//	@Description	Stops a storage pool
//	@Tags			storage
//	@Accept			json
//	@Produce		json
//	@Param			connection	query		string					true	"Connection ID"
//	@Param			pool		query		string					true	"Storage pool name"
//	@Success		200			{object}	map[string]interface{}	"{"message": string}"
//	@Failure		404			{object}	map[string]interface{}	"Storage pool not found"
//	@Failure		500			{object}	map[string]interface{}	"Internal Server Error"
//	@Router			/storage/pool/stop [post]
func (h *StorageHandler) StopPool(c *gin.Context) {
	name := c.Query("pool")
	if name == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "pool query parameter is required"})
		return
	}

	conn, err := getConnectionFromRequest(c, h.connMgr)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "connection not available"})
		return
	}

	hvConn := conn.GetConnect()

	pool, err := hvConn.LookupStoragePoolByName(name)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "storage pool not found"})
		return
	}
	defer func() {
		if err := pool.Free(); err != nil {
			// 记录错误但继续执行
			h.log.WithError(err).Warn("Failed to free storage pool")
		}
	}()

	if err := pool.Destroy(); err != nil {
		h.log.WithError(err).Error("Failed to stop storage pool")
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	h.log.WithField("name", name).Info("Storage pool stopped successfully")
	c.JSON(http.StatusOK, gin.H{"message": "storage pool stopped successfully"})
}

// ListVolumes returns all volumes in a pool
//
//	@Summary		List storage volumes
//	@Description	Returns all storage volumes in a pool
//	@Tags			storage
//	@Accept			json
//	@Produce		json
//	@Param			connection	query		string					true	"Connection ID"
//	@Param			pool		query		string					true	"Storage pool name"
//	@Success		200			{object}	map[string]interface{}	"{"volumes": []models.StorageVolumeSummary, "count": int}"
//	@Failure		404			{object}	map[string]interface{}	"Storage pool not found"
//	@Failure		500			{object}	map[string]interface{}	"Internal Server Error"
//	@Router			/storage/volumes [get]
func (h *StorageHandler) ListVolumes(c *gin.Context) {
	poolName := c.Query("pool")
	if poolName == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "pool query parameter is required"})
		return
	}

	conn, err := getConnectionFromRequest(c, h.connMgr)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "connection not available"})
		return
	}

	hvConn := conn.GetConnect()

	pool, err := hvConn.LookupStoragePoolByName(poolName)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "storage pool not found"})
		return
	}
	defer func() {
		if err := pool.Free(); err != nil {
			// 记录错误但继续执行
			h.log.WithError(err).Warn("Failed to free storage pool")
		}
	}()

	volumes, err := pool.ListAllStorageVolumes(0)
	if err != nil {
		h.log.WithError(err).Error("Failed to list volumes")
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	result := make([]models.StorageVolumeSummary, 0, len(volumes))
	for _, volume := range volumes {
		name, _ := volume.GetName()
		path, _ := volume.GetPath()

		result = append(result, models.StorageVolumeSummary{
			Name: name,
			Path: path,
			Type: "file",
		})

		if err := volume.Free(); err != nil {
			// 记录错误但继续执行
			h.log.WithError(err).Warn("Failed to free storage volume")
		}
	}

	c.JSON(http.StatusOK, gin.H{
		"volumes": result,
		"count":   len(result),
	})
}

// GetVolume returns a specific volume
//
//	@Summary		Get storage volume details
//	@Description	Returns detailed information about a specific storage volume
//	@Tags			storage
//	@Accept			json
//	@Produce		json
//	@Param			connection	query		string	true	"Connection ID"
//	@Param			pool		query		string	true	"Storage pool name"
//	@Param			volume		query		string	true	"Storage volume name"
//	@Success		200			{object}	models.StorageVolumeDetail
//	@Failure		404			{object}	map[string]interface{}	"Volume not found"
//	@Failure		500			{object}	map[string]interface{}	"Internal Server Error"
//	@Router			/storage/volume [get]
func (h *StorageHandler) GetVolume(c *gin.Context) {
	poolName := c.Query("pool")
	volumeName := c.Query("volume")
	if poolName == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "pool query parameter is required"})
		return
	}
	if volumeName == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "volume query parameter is required"})
		return
	}

	conn, err := getConnectionFromRequest(c, h.connMgr)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "connection not available"})
		return
	}

	hvConn := conn.GetConnect()

	pool, err := hvConn.LookupStoragePoolByName(poolName)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "storage pool not found"})
		return
	}
	defer func() {
		if err := pool.Free(); err != nil {
			// 记录错误但继续执行
			h.log.WithError(err).Warn("Failed to free storage pool")
		}
	}()

	volume, err := pool.LookupStorageVolByName(volumeName)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "volume not found"})
		return
	}
	defer func() {
		if err := volume.Free(); err != nil {
			// 记录错误但继续执行
			h.log.WithError(err).Warn("Failed to free storage volume")
		}
	}()

	path, _ := volume.GetPath()
	info, _ := volume.GetInfo()
	xmlDesc, _ := volume.GetXMLDesc(0)

	c.JSON(http.StatusOK, models.StorageVolumeDetail{
		Name:       volumeName,
		Path:       path,
		Type:       "file",
		Capacity:   info.Capacity,
		Allocation: info.Allocation,
		XMLConfig:  xmlDesc,
	})
}

// CreateVolume creates a new storage volume
//
//	@Summary		Create storage volume
//	@Description	Creates a new storage volume
//	@Tags			storage
//	@Accept			json
//	@Produce		json
//	@Param			connection	query		string						true	"Connection ID"
//	@Param			pool		query		string						true	"Storage pool name"
//	@Param			volume		body		models.CreateVolumeRequest	true	"Volume configuration"
//	@Success		201			{object}	map[string]interface{}		"{"message": string}"
//	@Failure		400			{object}	map[string]interface{}		"Bad Request"
//	@Failure		404			{object}	map[string]interface{}		"Storage pool not found"
//	@Failure		500			{object}	map[string]interface{}		"Internal Server Error"
//	@Router			/storage/volumes [post]
func (h *StorageHandler) CreateVolume(c *gin.Context) {
	poolName := c.Query("pool")
	if poolName == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "pool query parameter is required"})
		return
	}

	var req models.CreateVolumeRequest

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	conn, err := getConnectionFromRequest(c, h.connMgr)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "connection not available"})
		return
	}

	hvConn := conn.GetConnect()
	pool, err := hvConn.LookupStoragePoolByName(poolName)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "storage pool not found"})
		return
	}
	defer func() {
		if err := pool.Free(); err != nil {
			// 记录错误但继续执行
			h.log.WithError(err).Warn("Failed to free storage pool")
		}
	}()

	// Generate volume XML
	format := req.Format
	if format == "" {
		format = "qcow2"
	}

	volumeXML := fmt.Sprintf(`
<volume>
  <name>%s</name>
  <capacity unit="bytes">%d</capacity>
  <target>
    <format type="%s"/>
  </target>
</volume>`, req.Name, req.Capacity, format)

	volume, err := pool.StorageVolCreateXML(volumeXML, 0)
	if err != nil {
		h.log.WithError(err).Error("Failed to create volume")
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	defer func() {
		if err := volume.Free(); err != nil {
			// 记录错误但继续执行
			h.log.WithError(err).Warn("Failed to free storage volume")
		}
	}()

	h.log.WithFields(logrus.Fields{
		"pool":   poolName,
		"volume": req.Name,
	}).Info("Storage volume created successfully")

	c.JSON(http.StatusCreated, gin.H{"message": "volume created successfully"})
}

// DeleteVolume deletes a storage volume
//
//	@Summary		Delete storage volume
//	@Description	Deletes a storage volume
//	@Tags			storage
//	@Accept			json
//	@Produce		json
//	@Param			connection	query		string					true	"Connection ID"
//	@Param			pool		query		string					true	"Storage pool name"
//	@Param			volume		query		string					true	"Storage volume name"
//	@Success		200			{object}	map[string]interface{}	"{"message": string}"
//	@Failure		404			{object}	map[string]interface{}	"Volume not found"
//	@Failure		500			{object}	map[string]interface{}	"Internal Server Error"
//	@Router			/storage/volume [delete]
func (h *StorageHandler) DeleteVolume(c *gin.Context) {
	poolName := c.Query("pool")
	volumeName := c.Query("volume")
	if poolName == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "pool query parameter is required"})
		return
	}
	if volumeName == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "volume query parameter is required"})
		return
	}

	conn, err := getConnectionFromRequest(c, h.connMgr)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "connection not available"})
		return
	}

	hvConn := conn.GetConnect()

	pool, err := hvConn.LookupStoragePoolByName(poolName)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "storage pool not found"})
		return
	}
	defer func() {
		if err := pool.Free(); err != nil {
			// 记录错误但继续执行
			h.log.WithError(err).Warn("Failed to free storage pool")
		}
	}()

	volume, err := pool.LookupStorageVolByName(volumeName)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "volume not found"})
		return
	}
	defer func() {
		if err := volume.Free(); err != nil {
			// 记录错误但继续执行
			h.log.WithError(err).Warn("Failed to free storage volume")
		}
	}()

	if err := volume.Delete(0); err != nil {
		h.log.WithError(err).Error("Failed to delete volume")
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	h.log.WithFields(logrus.Fields{
		"pool":   poolName,
		"volume": volumeName,
	}).Info("Storage volume deleted successfully")

	c.JSON(http.StatusOK, gin.H{"message": "volume deleted successfully"})
}

// ListPoolsDefault lists storage pools on default connection
func (h *StorageHandler) ListPoolsDefault(c *gin.Context) {
	c.Params = append(c.Params, gin.Param{Key: "connection_id", Value: ""})
	h.ListPools(c)
}
